#include "speed.h"

static double RunningTime = 0;

void speed_all() {
    printf("Start testing the speed of each function...\n");
    printf("%-16s%-12s%-12s%-12s\n","Function", "Number", "Time", "Speed");
    speed_fp_add();
    speed_fp_sub();
    speed_fp_haf();
    speed_fp_dou();
    speed_fp_inv();
    speed_fp_mul();
    speed_point_add();
    speed_point_add_AJ();
    speed_point_dou();
    speed_point_mdo();
    speed_point_mul();
    speed_point_mul_fixed();
    speed_sm2_sign();
    speed_sm2_verify();
    speed_sm2_enc();
    speed_sm2_dec();
    speed_sm4_enc();
    speed_sm4_dec();
    speed_sm3();
    printf("The test is over.\n\n");
}

void speed_fp_add() {
    u32 n = 100000000;
    fp x, y, z, t;
    fp_fm_str(x, "E7BA3D4240D179AA38C580FFF968EE2EDB4A8EF6CF64E30A4B770A0CC69020ED");
    fp_fm_str(y, "FDDD52AF95B748A553D1B1E106627F901CD453F067A0D50202C672130C90F607");
    fp_fm_str(z, "0DDD52AF95B748A553D1B1E106627F901CD453F067A0D50202C672130C90F607");
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        fp_add(t, x, y);
        fp_add(t, x, z);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "fp_add", n << 1, RunningTime, (n << 1) / RunningTime);
}

void speed_fp_sub() {
    u32 n = 100000000;
    fp x, y, z, t;
    fp_fm_str(x, "E7BA3D4240D179AA38C580FFF968EE2EDB4A8EF6CF64E30A4B770A0CC69020ED");
    fp_fm_str(y, "FDDD52AF95B748A553D1B1E106627F901CD453F067A0D50202C672130C90F607");
    fp_fm_str(z, "0DDD52AF95B748A553D1B1E106627F901CD453F067A0D50202C672130C90F607");
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        fp_sub(t, x, y);
        fp_sub(t, x, z);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "fp_sub", n << 1, RunningTime, (n << 1) / RunningTime);
}

void speed_fp_haf() {
    u32 n = 10000000;
    fp x, y, t;
    fp_fm_str(x, "E7BA3D4240D179AA38C580FFF968EE2EDB4A8EF6CF64E30A4B770A0CC69020ED");
    fp_fm_str(y, "E7BA3D4240D179AA38C580FFF968EE2EDB4A8EF6CF64E30A4B770A0CC69020EC");
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        fp_haf(t, x);
        fp_haf(t, y);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "fp_haf", n << 1, RunningTime, (n << 1) / RunningTime);
}

void speed_fp_dou() {
    u32 n = 10000000;
    fp x, y, t;
    fp_fm_str(x, "E7BA3D4240D179AA38C580FFF968EE2EDB4A8EF6CF64E30A4B770A0CC69020ED");
    fp_fm_str(y, "17BA3D4240D179AA38C580FFF968EE2EDB4A8EF6CF64E30A4B770A0CC69020ED");
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        fp_dou(t, x);
        fp_dou(t, y);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "fp_dou", n << 1, RunningTime, (n << 1) / RunningTime);
}

void speed_fp_inv() {
    u32 n = 100000;
    fp x, t;
    fp_fm_str(x, "E7BA3D4240D179AA38C580FFF968EE2EDB4A8EF6CF64E30A4B770A0CC69020ED");
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        fp_inv(t, x);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "fp_inv", n << 1, RunningTime, (n << 1) / RunningTime);
}

void speed_fp_mul() {
    u32 n = 10000000;
    fp x, y, z;
    fp_fm_str(x, "E7BA3D4240D179AA38C580FFF968EE2EDB4A8EF6CF64E30A4B770A0CC69020ED");
    fp_fm_str(y, "9DDD52AF95B748A553D1B1E106627F901CD453F067A0D50202C672130C90F607");
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        fp_mul(z, x, y);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "fp_mul", n << 1, RunningTime, (n << 1) / RunningTime);
}

void speed_point_add() {
    u32 n = 1000000;
    point p, q;
    jpoint jp, jq, jt;
    fp_fm_str(p.x, "E7BA3D4240D179AA38C580FFF968EE2EDB4A8EF6CF64E30A4B770A0CC69020ED");
    fp_fm_str(p.y, "9DDD52AF95B748A553D1B1E106627F901CD453F067A0D50202C672130C90F607");
    fp_fm_str(q.x, "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D");
    fp_fm_str(q.y, "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2");
    jpoint_set(&jp, p.x, p.y, one);
    jpoint_set(&jq, q.x, q.y, one);
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        jpoint_add(&jt, &jp, &jq);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "jpoint_add", n, RunningTime, n / RunningTime);
}

void speed_point_add_AJ() {
    u32 n = 1000000;
    point q, t;
    jpoint jp, jt;
    fp_fm_str(jp.x, "E7BA3D4240D179AA38C580FFF968EE2EDB4A8EF6CF64E30A4B770A0CC69020ED");
    fp_fm_str(jp.y, "9DDD52AF95B748A553D1B1E106627F901CD453F067A0D50202C672130C90F607");
    fp_fm_str(jp.z, "0000000000000000000000000000000000000000000000000000000000000001");
    fp_fm_str(q.x, "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D");
    fp_fm_str(q.y, "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2");
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        jpoint_add_AJ(&jt, &jp, &q);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "jpoint_add_aj", n, RunningTime, n / RunningTime);
}

void speed_point_dou() {
    u32 n = 1000000;
    point p;
    jpoint jp, jt;
    fp_fm_str(p.x, "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D");
    fp_fm_str(p.y, "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2");
    jpoint_set(&jp, p.x, p.y, one);
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        jpoint_dou(&jt, &jp);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "jpoint_dou", n, RunningTime, n / RunningTime);
}

void speed_point_mdo() {
    u32 n = 1000000;
    point p;
    jpoint jp, jt;
    u32 m = 6;
    fp_fm_str(p.x, "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D");
    fp_fm_str(p.y, "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2");
    jpoint_set(&jp, p.x, p.y, one);
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        jpoint_mdo(&jt, m, &jp);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "jpoint_mutdou", n, RunningTime, n / RunningTime);
}

void speed_point_mul() {
    u32 n = 10000;
    fp k;
    point p;
    jpoint jp, jt;
    fp_fm_str(k, "3945208F7B2144B13F36E38AC6D39F95889393692860B51A42FB81EF4DF7C5B8");
    fp_fm_str(p.x, "04EBFC718E8D1798620432268E77FEB6415E2EDE0E073C0F4F640ECD2E149A73");
    fp_fm_str(p.y, "E858F9D81E5430A57B36DAAB8F950A3C64E6EE6A63094D99283AFF767E124DF0");
    jpoint_set(&jp, p.x, p.y, one);
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        jpoint_mul(&jt, k, &jp);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "jpoint_mul", n, RunningTime, n / RunningTime);
}

void speed_point_mul_fixed() {
    u32 n = 10000;
    fp k;
    jpoint jt;
    fp_fm_str(k, "3945208F7B2144B13F36E38AC6D39F95889393692860B51A42FB81EF4DF7C5B8");
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        jpoint_mul_fixed(&jt, k);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "jpoint_fixmul", n, RunningTime, n / RunningTime);
}

void speed_sm2_sign() {
    u32 n = 10000;
    char msq[] = "message digest";
    char id[] = "1234567812345678";
    u8 dgst[32];
    sm2_private_key prikey;
    sm2_signature signature;

    byt_fm_str(prikey.prikey,   "3945208F7B2144B13F36E38AC6D39F95889393692860B51A42FB81EF4DF7C5B8");
    byt_fm_str(prikey.pubkey.x, "09F9DF311E5421A150DD7D161E4BC5C672179FAD1833FC076BB08FF356F35020");
    byt_fm_str(prikey.pubkey.y, "CCEA490CE26775A52DC6EA718CC1AA600AED05FBF35E084A6632F6072DA9AD13");

    sm2_sign_init(dgst, &prikey.pubkey, id, strlen(id), (u8*) msq, strlen(msq));

    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        sm2_sign(&signature, &prikey, dgst);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "sm2_sign", n, RunningTime, n / RunningTime);
}

void speed_sm2_verify() {
    u32 n = 10000;
    char msq[] = "message digest";
    char id[] = "1234567812345678";
    sm2_public_key pubkey;
    sm2_signature signature;
    u8 dgst[32];
    u8 sig_der[] = {0x30, 0x46, 0x02, 0x21, 0x00, 0xf5, 0xa0, 0x3b, 0x06, 0x48, 0xd2, 0xc4, 0x63, 0x0e, 0xea, 0xc5,
                    0x13, 0xe1,
                    0xbb, 0x81, 0xa1, 0x59, 0x44, 0xda, 0x38, 0x27, 0xd5, 0xb7, 0x41, 0x43, 0xac, 0x7e, 0xac, 0xee,
                    0xe7, 0x20,
                    0xb3, 0x02, 0x21, 0x00, 0xb1, 0xb6, 0xaa, 0x29, 0xdf, 0x21, 0x2f, 0xd8, 0x76, 0x31, 0x82, 0xbc,
                    0x0d, 0x42,
                    0x1c, 0xa1, 0xbb, 0x90, 0x38, 0xfd, 0x1f, 0x7f, 0x42, 0xd4, 0x84, 0x0b, 0x69, 0xc4, 0x85, 0xbb,
                    0xc1, 0xaa};
    const u8 *_sig_der = sig_der;
    u64 sig_len = sizeof(sig_der);
    byt_fm_str(pubkey.x, "09F9DF311E5421A150DD7D161E4BC5C672179FAD1833FC076BB08FF356F35020");
    byt_fm_str(pubkey.y, "CCEA490CE26775A52DC6EA718CC1AA600AED05FBF35E084A6632F6072DA9AD13");
    sm2_sig_from_der(&signature, &_sig_der, &sig_len);
    sm2_verify_init(dgst, &pubkey, id, strlen(id), (u8*) msq, strlen(msq));
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        sm2_verify(&signature, &pubkey, dgst);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "sm2_verify", n, RunningTime, n / RunningTime);
}

void speed_sm2_enc() {
    u32 n = 10000;
    char msq[] = "encryption standard";
    sm2_point pubkey = {0};
    sm2_ciptext ctext = {0};
    u8 ciphertext[sizeof(msq)] = {0};
    ctext.ctext = ciphertext;

    byt_fm_str(pubkey.x, "09F9DF311E5421A150DD7D161E4BC5C672179FAD1833FC076BB08FF356F35020");
    byt_fm_str(pubkey.y, "CCEA490CE26775A52DC6EA718CC1AA600AED05FBF35E084A6632F6072DA9AD13");

    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        sm2_encrypt(&ctext, &pubkey, msq);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "sm2_enc", n, RunningTime, n / RunningTime);
}

void speed_sm2_dec() {
    u32 n = 10000;
    char msq[] = "encryption standard";
    sm2_private_key prikey;
    sm2_ciptext ct = {0};
    u8 ct_der[] = {0x30, 0x7c, 0x02, 0x20, 0x04, 0xeb, 0xfc, 0x71, 0x8e, 0x8d, 0x17, 0x98, 0x62, 0x04, 0x32, 0x26, 0x8e,
                   0x77,
                   0xfe, 0xb6, 0x41, 0x5e, 0x2e, 0xde, 0x0e, 0x07, 0x3c, 0x0f, 0x4f, 0x64, 0x0e, 0xcd, 0x2e, 0x14, 0x9a,
                   0x73,
                   0x02, 0x21, 0x00, 0xe8, 0x58, 0xf9, 0xd8, 0x1e, 0x54, 0x30, 0xa5, 0x7b, 0x36, 0xda, 0xab, 0x8f, 0x95,
                   0x0a,
                   0x3c, 0x64, 0xe6, 0xee, 0x6a, 0x63, 0x09, 0x4d, 0x99, 0x28, 0x3a, 0xff, 0x76, 0x7e, 0x12, 0x4d, 0xf0,
                   0x04,
                   0x20, 0x59, 0x98, 0x3c, 0x18, 0xf8, 0x09, 0xe2, 0x62, 0x92, 0x3c, 0x53, 0xae, 0xc2, 0x95, 0xd3, 0x03,
                   0x83,
                   0xb5, 0x4e, 0x39, 0xd6, 0x09, 0xd1, 0x60, 0xaf, 0xcb, 0x19, 0x08, 0xd0, 0xbd, 0x87, 0x66, 0x04, 0x13,
                   0x21,
                   0x88, 0x6c, 0xa9, 0x89, 0xca, 0x9c, 0x7d, 0x58, 0x08, 0x73, 0x07, 0xca, 0x93, 0x09, 0x2d, 0x65, 0x1e,
                   0xfa};
    u8 pt[sizeof(msq) - 1];
    const u8 *_ct_der = ct_der;
    u64 l = sizeof(ct_der);
    u8 ciphertext[sizeof(ct_der)];
    ct.ctext = ciphertext;
    sm2_ciptext_from_der(&ct, &_ct_der, &l);
    byt_fm_str(prikey.prikey,   "3945208F7B2144B13F36E38AC6D39F95889393692860B51A42FB81EF4DF7C5B8");
    byt_fm_str(prikey.pubkey.x, "09F9DF311E5421A150DD7D161E4BC5C672179FAD1833FC076BB08FF356F35020");
    byt_fm_str(prikey.pubkey.y, "CCEA490CE26775A52DC6EA718CC1AA600AED05FBF35E084A6632F6072DA9AD13");
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        sm2_decrypt(pt, &prikey, &ct);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f ops/s\r\n", "sm2_dec", n, RunningTime, n / RunningTime);
}

void speed_sm4_enc() {
    u32 n = 10000000;
    u8 key[16] = {0};
    u8 pt[16] = {0};
    u8 ct[16] = {0};
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        sm4_encrypt(ct, pt, key);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f Mbps/s\r\n", "sm4_enc", n, RunningTime, (double) (n << 7) / 1000000 / RunningTime);}

void speed_sm4_dec() {
    u32 n = 10000000;
    u8 key[16] = {0};
    u8 pt[16] = {0};
    u8 ct[16] = {0};
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        sm4_decrypt(pt, ct, key);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f Mbps/s\r\n", "sm4_dec", n, RunningTime, (double) (n << 7) / 1000000 / RunningTime);
}

void speed_sm3() {
    u32 n = 10000000;
    u8 message[] = "abc";
    u32 digest[8];
    DWORD start, end;
    start = GetTickCount();
    for (int i = 0; i < n; ++i) {
        sm3_compress(message, digest);
    }
    end = GetTickCount();
    RunningTime = ((double) (end - start) / CLK_TCK);
    printf("%-16s%-12d%-12.3f%.3f Mbps/s\r\n", "sm3", n, RunningTime, (double) ((n/1000000) << 9) / RunningTime);
}

